package cn.wolfcode.luowowo.interceptor;

import cn.wolfcode.luowowo.annotation.RequireLogin;
import cn.wolfcode.luowowo.cache.service.IUserInfoRedisService;
import cn.wolfcode.luowowo.domain.UserInfo;
import cn.wolfcode.luowowo.util.JsonResult;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *  用户登录检查
 *  (操作某个东西前,检查用户是否登录了)
 */
public class CheckLoginInterceptor implements HandlerInterceptor{

    @Autowired
    private IUserInfoRedisService userInfoRedisService;


    // 实现登录拦截
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{

        // 处理跨域请求被拦截问题(若是跨域请求我直接放行,不拦截你)
        // HandlerMethod 代指动态请求
        // HandlerMethod 请求映射方法在SpringMvc封装对象
        /**
         * 1.spring容器启动时,会解析所有的@RequestMapping标签
         * 将解析到所有请求映射方法相关信息(路径,方法名,方法参数...)
         * 封装成HandlerMethod对象
         * 2.将步骤1得到的所有请求映射方法,封装大奥一个类似map数据
         * key值是映射路径 value值就就会HandlerMethod对象
         * Map<String, HandlerMethod> map
         * key                            value
         * /users/currentUser            currentUser映射方法对应:HandlerMethod对象
         * /users/login                  login映射方法对应:HandlerMethod
         * 3.当浏览器发起请求时, SpringMVC前端控制器会解析请求路径
         * http://localhost:8080/users/currentUser
         *
         * url(key) :/users/currentUser
         * HandlerMethod value = map.get("/users/currentUser")
         *
         * 通过一系列操作得到value对象,然后传入到interceptor拦截器
         * preHandler方法中(作为参数传入)
         */
        if(!(handler instanceof HandlerMethod)){//判断是不是同一类型
            return true;//放行
        }

        // <1>.判断当前请求方法是否贴有@RequireLogin注解
        HandlerMethod hm= (HandlerMethod)handler;

        // 1.从请求中获取令牌
        String token = request.getHeader("token");
        // 2.通过令牌获取当前登录用户
        UserInfo user = userInfoRedisService.getUserByToken(token);

        // <2>.若有进行登录校验
        if(hm.hasMethodAnnotation(RequireLogin.class)){
            // 3.若当前登录用户为空,提示请登录
            if(user ==null){
                // json数中文转码(转成json数据)
                response.setContentType("application/json;charset=utf-8");
                // 没登录,返回没登录的提示
                response.getWriter().write(JSON.toJSONString(JsonResult.noLogin()));
                // 不放行
                return false;
            }
        }
        // <3>.若没有,放行
        return true;
    }
}
